package com.markul.android.ui.mark

import android.content.Context
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Bundle
import android.os.Handler
import android.text.format.DateFormat
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.EditText
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.baidu.location.BDLocation
import com.baidu.location.BDLocationListener
import com.baidu.location.LocationClient
import com.baidu.location.LocationClientOption
import com.baidu.mapapi.map.*
import com.baidu.mapapi.model.LatLng
import com.baidu.mapapi.search.core.SearchResult
import com.baidu.mapapi.search.geocode.*
import com.markul.android.MarkulApplication
import com.markul.android.R
import com.markul.android.logic.model.MarkIconData
import com.markul.android.logic.model.room.PublicAlbum
import com.markul.android.logic.model.room.PublicPhoto
import com.markul.android.logic.room.Album
import com.markul.android.logic.room.AlbumInfo
import com.markul.android.logic.room.Photo
import com.markul.android.ui.UiTool
import com.markul.android.ui.location.GetAlbumLocation
import com.markul.android.ui.mark.adapter.*
import com.markul.android.ui.mark.markFragment.SyncFragment
import com.markul.android.ui.search.SearchActivity
import com.zhihu.matisse.Matisse
import com.zhihu.matisse.MimeType
import com.zhihu.matisse.engine.impl.GlideEngine
import com.zhihu.matisse.filter.Filter
import com.zhihu.matisse.internal.entity.CaptureStrategy
import kotlinx.android.synthetic.main.activity_mark.*
import kotlinx.android.synthetic.main.activity_mark.addressText
import kotlinx.android.synthetic.main.activity_mark.backBtn
import kotlinx.android.synthetic.main.activity_mark.chooseIconRecycler
import kotlinx.android.synthetic.main.activity_mark.clickLayout
import kotlinx.android.synthetic.main.activity_mark.dateText
import kotlinx.android.synthetic.main.activity_mark.keyText
import kotlinx.android.synthetic.main.activity_mark.picRecycler
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import kotlin.collections.ArrayList


class MarkActivity : AppCompatActivity(), OnItemClickListener, OnGetGeoCoderResultListener {

    private val REQUEST_CODE_CHOOSE = 300 //照片选择回调
    private var picStringList = ArrayList<String>()
    private var IconList = ArrayList<Int>()
    var handler = Handler()
    var chooseIconList = ArrayList<Int>()
    val getAlbumLocation = GetAlbumLocation()
    var text = ""
    var lat: Double = 0.0
    var lng: Double = 0.0
    var time = ""

    //最大能上传的照片
    private val maxNum = 50

    // 地图View实例
    private var mLocClient: LocationClient? = null
    val myListener = MyLocationListener()
    var mMapView: MapView? = null
    var mBaiduMap: BaiduMap? = null
    var mSearch: GeoCoder? = null

    // 用于设置个性化地图的样式文件
    private val CUSTOM_FILE_NAME_CX = "custom_map_config_CX.sty"

    // 是否首次定位
    var isFirstLoc = true
    var option: LocationClientOption = LocationClientOption()

    //Adapter实例化
    private var markAdapter = MarkAdapter(picStringList, maxNum)
    private var markIconAdapter = MarkIconAdapter(IconList)
    private var markChooseIconAdapter = MarkChooseIconAdapter(chooseIconList)
    private var iconLabelAdapter = IconLabelAdapter(MarkIconData.labelList)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_mark)

        UiTool.hideStatusNavigationBar(this, true)



        if (intent.getStringExtra("who") == "our") {
            replaceFragment(SyncFragment())
        }

        //地图初始化
        mMapView = findViewById<View>(R.id.bmapView) as MapView
        mBaiduMap = mMapView!!.map
        mMapView!!.showZoomControls(false)
        mMapView!!.showScaleControl(false)
        // 初始化搜索模块，注册事件监听
        mSearch = GeoCoder.newInstance()
        mSearch!!.setOnGetGeoCodeResultListener(this)
        //改变地图样式
        changeMapStyle()
        //改变定位图标
        changeLocationIcon()
        //初始化定位
        initLocation()
//可选，是否需要周边POI信息，默认为不需要，即参数为false
//如果开发者需要获得周边POI信息，此处必须为true
        IconList.addAll(MarkIconData.emojiIconList)
        val viewModel: MarkViewModel by viewModels()

        initRecyclerview()
        backBtn.setOnClickListener {
            finish()
        }
        uploadBtn.setOnClickListener {
            val editText = findViewById<EditText>(R.id.editTextTextMultiLine)
            text = editText.text.toString()
            var icon1: Int?
            var icon2: Int?
            var icon3: Int?
            when (chooseIconList.size) {
                0 -> {
                    icon1 = null
                    icon2 = null
                    icon3 = null
                }
                1 -> {
                    icon1 = chooseIconList[0]
                    icon2 = null
                    icon3 = null
                }
                2 -> {
                    icon1 = chooseIconList[0]
                    icon2 = chooseIconList[1]
                    icon3 = null
                }
                else -> {
                    icon1 = chooseIconList[0]
                    icon2 = chooseIconList[1]
                    icon3 = chooseIconList[2]
                }
            }
            if (picStringList.isNotEmpty()) {
                if (intent.getStringExtra("who") == "our") {
                    for (i in picStringList) {
                        val photo = PublicPhoto(
                            "$i",
                            MarkulApplication.publicAlbumMaxId,
                            MarkulApplication.userId
                        )
                        viewModel.addPPhoto(photo)
                    }
                    val pAlbum = PublicAlbum(
                        MarkulApplication.publicRoomId, text, lat, lng, time, icon1, icon2, icon3
                    )
                    viewModel.addPAlbum(pAlbum)
                } else {
                    for (i in picStringList) {
                        val photo = Photo("$i", MarkulApplication.albumMaxId)
                        viewModel.addPhoto(photo)
                    }
                    val album = Album(
                        MarkulApplication.userId, text, lat, lng, time, icon1, icon2, icon3
                    )
                    viewModel.addAlbum(album)
                }
                picStringList = ArrayList()
                //告知其他页面已经更新
                MarkulApplication.load = true
                finish()
            } else {
                Toast.makeText(this, "请选择要上传的图片", Toast.LENGTH_SHORT).show()
            }
        }
        clickLayout.setOnClickListener {
            val intent = Intent(this, SearchActivity::class.java)
            startActivityForResult(intent, 1)
        }
    }

    private fun initRecyclerview() {
        //图片Recycle
        picRecycler.layoutManager =
            StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.HORIZONTAL)
        picRecycler.adapter = markAdapter
        //iconRecycle
        iconRecycler.layoutManager =
            StaggeredGridLayoutManager(9, StaggeredGridLayoutManager.VERTICAL)
        iconRecycler.adapter = markIconAdapter
        //icon显示区Recycle
        chooseIconRecycler.layoutManager =
            StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.HORIZONTAL)
        chooseIconRecycler.adapter = markChooseIconAdapter
        //Label栏
        iconCategoryRecycler.layoutManager =
            StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.HORIZONTAL)
        iconCategoryRecycler.adapter = iconLabelAdapter
//        val layoutManager=LinearLayoutManager(this)
//        layoutManager.orientation=LinearLayoutManager.HORIZONTAL
//        iconRecycler.layoutManager=layoutManager

//        iconRecycler.addItemDecoration(object : ItemDecoration() {
//            override fun getItemOffsets(
//                outRect: Rect,
//                view: View,
//                parent: RecyclerView,
//                state: RecyclerView.State
//            ) {
//                super.getItemOffsets(outRect, view, parent, state)
//                outRect.set(-20,0,0,0)
//            }}
//            )
        markAdapter.setOnMyClickListener(this)
        markIconAdapter.setOnMyClickListener(this)
        markChooseIconAdapter.setOnMyClickListener(this)
        iconLabelAdapter.setOnMyClickListener(this)
    }

    private fun selectPhoto(num: Int) {
        Matisse.from(this) //  .choose(MimeType.ofAll(),false)               //false表示不能同时选照片和视频
            .choose(MimeType.ofImage()) //选择类,日后单独配置
            //拍照需要的两个（写完这个就会有照相那个图标了）
            .capture(true)
            .captureStrategy(
                CaptureStrategy(
                    true,
                    "com.markul.android.ui.mark.fileprovider",
                    "test"
                )
            ) //最后文件存储地址：Pictures/test
            .countable(true) //选择时是否计数
            .maxSelectable(num) //最大可选择数
            .addFilter(GifSizeFilter(320, 320, 5 * Filter.K * Filter.K)) //过滤器   5M大小
            //          .gridExpectedSize(resources.getDimensionPixelSize(R.dimen.grid_expected_size)) //每个图片方格的大小
            .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) //选择方向
            .thumbnailScale(0.85f) //刚进入图片选择页面后图片的清晰度
            .imageEngine(GlideEngine())//图片引擎
            .theme(R.style.Matisse_Dracula)//主题这里使用默认的
            .originalEnable(true) //原图按钮
            .forResult(REQUEST_CODE_CHOOSE) //请求码
    }

    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
            //获取到的地址只是相对地址，但可以给图片加载，若要上传图片，需获取真实本地地址
            picStringList.addAll(Matisse.obtainPathResult(data)) //真实地址
            for (i in 0 until picStringList.size) {
                Log.i("ceshi", "onActivityResult:获取到的地址为: " + picStringList[i])
            }
            val albumInfo: AlbumInfo = getAlbumLocation.getPhotoInfo(picStringList[0])
            lat = albumInfo.lat
            lng = albumInfo.lng
            time = if (albumInfo.time != null) {
                val time0 = System.currentTimeMillis()
                DateFormat.format("yyyy" + "年" + "MM" + "月" + "dd" + "日", time0).toString()
                "${albumInfo.time.substring(0, 4)}年${
                    albumInfo.time.substring(
                        5,
                        7
                    )
                }月${albumInfo.time.substring(5, 7)}日"
            } else {
                val time0 = System.currentTimeMillis()
                DateFormat.format("yyyy" + "年" + "MM" + "月" + "dd" + "日", time0).toString()
            }
            dateText.text = time
            setCenter(LatLng(lat, lng))
            searchAddressByLocation(LatLng(lat, lng))
            markAdapter.notifyDataSetChanged()
            val handler1 = Handler()
            //设置延时让画面先加载好
            handler1.postDelayed(
                Runnable {
                    addMarker(LatLng(lat, lng), MarkulApplication.headImage)
                }, 1000
            )
        } else if (resultCode == 1) {
            run {
                if (data?.getDoubleExtra(
                        "lat",
                        0.000000
                    )!! in lat - 0.05..lat + 0.05 && data?.getDoubleExtra(
                        "lng",
                        0.000000
                    )!! in lng - 0.05..lng + 0.05
                ) {
                    var point = LatLng(
                        data?.getDoubleExtra("lat", 0.000000)!!,
                        data?.getDoubleExtra("lng", 0.000000)!!
                    )
                    setCenter(point)
                    keyText.text = data?.getStringExtra("key")
                    Log.i("12345","xxxx${keyText.text}")
                    addressText.text = data?.getStringExtra("address")
                    val handler1 = Handler()
                    //设置延时让画面先加载好
                    handler1.postDelayed(
                        Runnable {
                            addMarker(point, MarkulApplication.headImage)
                        }, 1000
                    )
                } else {
                    Toast.makeText(this, "请不要选择离拍摄地点太远的地方哟！", Toast.LENGTH_LONG).show()
                }

            }
        }
    }

    override fun onItemAddClick(position: Int) {
        selectPhoto(maxNum - picStringList.size)
    }

    override fun onItemDelClick(position: Int) {
        picStringList.removeAt(position)
        markAdapter.notifyDataSetChanged()
    }

    override fun onItemPicClick(position: Int) {
        Toast.makeText(this, "点击图片", Toast.LENGTH_SHORT).show()
    }

    override fun onIconClick(position: Int) {
        if (chooseIconList.size < 3) {
            chooseIconList.add(IconList[position])
        } else {
            Toast.makeText(this, "最多选择三个图标哟！", Toast.LENGTH_SHORT).show()
        }
        markChooseIconAdapter.notifyDataSetChanged()
    }

    override fun onChooseIconClick(position: Int) {
        chooseIconList.remove(chooseIconList[position])
        markChooseIconAdapter.notifyDataSetChanged()
    }

    override fun onLabelClick(position: Int) {
        Log.i("123", "$position")
        IconList.clear()
        IconList.addAll(MarkIconData.IconList(MarkIconData.labelList[position]))
        Log.i("123", "$IconList")
        markIconAdapter.notifyDataSetChanged()
    }

    //设置地图中心
    private fun setCenter(point: LatLng) {
        //设定中心点坐标
        //定义地图状态
        val mMapStatus: MapStatus = MapStatus.Builder()
            .target(point)
            .build()
        //定义MapStatusUpdate对象，以便描述地图状态将要发生的变化
        val mMapStatusUpdate = MapStatusUpdateFactory
            .newMapStatus(mMapStatus)
        //改变地图状态
        mBaiduMap!!.setMapStatus(mMapStatusUpdate)
    }

    private fun changeMapStyle() {
        // 构建地图状态
        val builder = MapStatus.Builder()
        // 更新地图
        mMapView!!.map.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()))
        // 获取.sty文件路径
        val customStyleFilePath: String? =
            getCustomStyleFilePath(this, CUSTOM_FILE_NAME_CX)
        // 设置个性化地图样式文件的路径和加载方式
        mMapView!!.setMapCustomStylePath(customStyleFilePath)
        // 动态设置个性化地图样式是否生效
        mMapView!!.setMapCustomStyleEnable(true)
    }

    private fun changeLocationIcon() {
        val mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL
        val accuracyCircleFillColor = -0x55000078
        val accuracyCircleStrokeColor = 0x55ff0100
        //修改为自定义图层
        var mcurrentMarker = BitmapDescriptorFactory.fromResource(MarkulApplication.headImage)
        mBaiduMap!!.setMyLocationConfiguration(
            MyLocationConfiguration(
                mCurrentMode, true, mcurrentMarker,
                accuracyCircleFillColor, accuracyCircleStrokeColor
            )
        )
    }

    private fun initLocation() {
        // 开启定位图层
        mBaiduMap!!.isMyLocationEnabled = true
        // 定位初始化
        mLocClient = LocationClient(this)
        mLocClient!!.registerLocationListener(myListener)
        val option = LocationClientOption()
        // 打开gps
        option.isOpenGps = true
        // 设置坐标类型
        option.locationMode = LocationClientOption.LocationMode.Hight_Accuracy
        option.setCoorType("bd09ll")
        option.setScanSpan(1000)
        mLocClient!!.locOption = option
        mLocClient!!.start()
    }

    override fun onResume() {
        super.onResume()

        //在activity执行onResume时执行mMapView. onResume ()，实现地图生命周期管理
        mMapView!!.onResume()
    }

    override fun onPause() {
        super.onPause()
        //在activity执行onPause时执行mMapView. onPause ()，实现地图生命周期管理
        mMapView!!.onPause()
    }

    override fun onDestroy() {
        // 退出时销毁定位
        // 释放检索对象
        mSearch!!.destroy()
        mLocClient!!.stop()
        mBaiduMap!!.isMyLocationEnabled = false
        mMapView!!.onDestroy()
        mMapView = null
        super.onDestroy()
        //在activity执行onDestroy时执行mMapView.onDestroy()，实现地图生命周期管理
    }

    //获取个性化地图文件地址
    private fun getCustomStyleFilePath(context: Context, customStyleFileName: String): String? {
        var outputStream: FileOutputStream? = null
        var inputStream: InputStream? = null
        var parentPath: String? = null
        try {
            inputStream = context.assets.open("customConfigdir/$customStyleFileName")
            val buffer = ByteArray(inputStream.available())
            inputStream.read(buffer)
            parentPath = context.filesDir.absolutePath
            val customStyleFile = File("$parentPath/$customStyleFileName")
            if (customStyleFile.exists()) {
                customStyleFile.delete()
            }
            customStyleFile.createNewFile()
            outputStream = FileOutputStream(customStyleFile)
            outputStream.write(buffer)
        } catch (e: IOException) {
            Log.e("CustomMapDemo", "Copy custom style file failed", e)
        } finally {
            try {
                inputStream?.close()
                outputStream?.close()
            } catch (e: IOException) {
                Log.e("CustomMapDemo", "Close stream failed", e)
                return null
            }
        }
        return "$parentPath/$customStyleFileName"
    }

    //定位监听器
    inner class MyLocationListener : BDLocationListener {
        override fun onReceiveLocation(location: BDLocation) {
            // MapView 销毁后不在处理新接收的位置
            if (location == null || mMapView == null) {
                return
            }
            val locData = MyLocationData.Builder()
                .accuracy(location.radius) // 设置定位数据的精度信息，单位：米
                .direction(location.direction) // 此处设置开发者获取到的方向信息，顺时针0-360
                .latitude(23.0540551376)
                .longitude(113.4130708748)
                .build()
            // 设置定位数据, 只有先允许定位图层后设置数据才会生效
            mBaiduMap!!.setMyLocationData(locData)
            if (isFirstLoc) {
                isFirstLoc = false
                val latLng = LatLng(23.0540551376, 113.4130708748)
                val builder = MapStatus.Builder()
                builder.target(latLng).zoom(15.0f)
                mBaiduMap!!.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()))
            }
        }
    }

    //增加打卡点
    private fun addMarker(point: LatLng, picId: Int?) {
        //构建Marker图标
        var bitmap: BitmapDescriptor
        if (picId == null) {
            bitmap = BitmapDescriptorFactory
                .fromResource(MarkulApplication.headImage)
        } else {
            bitmap = BitmapDescriptorFactory
                .fromResource(picId)
        }
        //构建MarkerOption，用于在地图上添加Marker
        val option: OverlayOptions = MarkerOptions()
            .position(point)
            .icon(bitmap)
            .perspective(true)
            .animateType(MarkerOptions.MarkerAnimateType.grow)
        //在地图上添加Marker，并显示
        mBaiduMap!!.addOverlay(option)
    }

    private fun replaceFragment(fragment: Fragment) {
        val fragmentManager = supportFragmentManager
        val transaction = fragmentManager.beginTransaction()
        transaction.replace(R.id.checkBoxLayout, fragment)
        transaction.commit()
    }

    fun searchAddressByLocation(point: LatLng) {
        val radius: Int = 100
        var version = 1
        // 反Geo搜索
        val reverseGeoCodeOption = ReverseGeoCodeOption()
            .location(point) // 设置反地理编码位置坐标
            .newVersion(version) // 设置是否返回新数据 默认值0不返回，1返回
            .radius(radius) //  POI召回半径，允许设置区间为0-1000米，超过1000米按1000米召回。默认值为1000
            .pageNum(0)
        // 发起反地理编码请求，该方法必须在监听之后执行，否则会在某些场景出现拿不到回调结果的情况
        mSearch!!.reverseGeoCode(reverseGeoCodeOption)
    }

    //逆地理编码查询
    override fun onGetReverseGeoCodeResult(result: ReverseGeoCodeResult?) {
        if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
            Toast.makeText(this, "抱歉，未能找到结果", Toast.LENGTH_LONG).show()
            return
        }
        val bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.icon_add)
        // 添加poi
        mBaiduMap!!.addOverlay(MarkerOptions().position(result.location).icon(bitmapDescriptor))
        // 获取周边poi结果
        if (result.poiList != null) {
            val poiList = result.poiList
            keyText.text = poiList[0].getName()
            addressText.text = poiList[0].getAddress()
        } else if (result.poiList == null && result.address !="" ) {
            keyText.text = result.addressDetail.city
            addressText.text = "${result.addressDetail.countryName}-${result.addressDetail.province}"
        } else {
            Toast.makeText(this, "抱歉,无法识别该照片地址", Toast.LENGTH_LONG).show()
        }
    }

    override fun onGetGeoCodeResult(result: GeoCodeResult?) {}

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.getAction()) {
            MotionEvent.ACTION_UP ->
                //设置延时让画面先加载好
                handler.postDelayed(
                    Runnable {
                        UiTool.hideStatusNavigationBar(this, true)
                    }, 3000
                )
        }
        return super.dispatchTouchEvent(ev)
    }
}